<!doctype html>
<!--suppress ALL -->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>ManaPHP Debugger</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css">
    <!--[if lt IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/response.js/respond.min.js"></script>
    <![endif]-->
    <style>
        #global tr td:nth-child(1) {
            width: 5%;
        }

        #global tr td:nth-child(2) {
            width: 20%;
        }

        body {
            overflow-y: scroll;
        }

        table pre {
            border: none;
            padding: 0;
            margin: 0;
            background-color: transparent;
            white-space: pre-wrap;
            word-wrap: break-word;
            max-height: 80px;
        }

        #dependencies pre {
            max-height: 200px;
        }

        #config pre {
            max-height: 500px;
        }

        .debugger {
            position: fixed;
            top: 1px;
            left: 1px;
            z-index: 1000000;
            width: 80px;
            border-radius: 5px;
            background-color: lightskyblue;
            margin: 0;
            padding: 0;
            text-align: center;
            box-sizing: border-box;
            line-height: 21px;
            font-family: Arial, sans-serif;
            opacity: 0.8;
        }

        .debugger a {
            display: block;
            color: red;
            text-decoration: none;
        }

        .warning {
            color: red;
        }
    </style>
</head>
<body>
<div class="container" id="app">
    <ul class="nav nav-tabs" id="tabs">
        <li><a href="#basic" data-toggle="tab">Basic</a></li>
        <li><a href="#dependencies" data-toggle="tab">Dependencies</a></li>
        <li><a href="#contexts" data-toggle="tab">Contexts</a></li>
        <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Global <b class="caret"></b></a>
            <ul class="dropdown-menu">
                <li v-for="(value, name) in dependencies['ManaPHP\\Http\\RequestInterface'].properties.context"
                    v-if="typeof value === 'object' && value !== null">
                    <a data-toggle="tab" @click="global_type=name" href="#global">{{name}}
                        <span v-if="!Object.keys(value).length">*</span>
                    </a>
                </li>
            </ul>
        </li>
        <li><a href="#view" data-toggle="tab">View</a></li>
        <li><a href="#config" data-toggle="tab">Config</a></li>
        <li><a href="#log" data-toggle="tab">Log</a></li>
        <li><a href="#events" data-toggle="tab">Events</a></li>
        <li><a href="#sql" data-toggle="tab">SQL</a></li>
        <li><a href="#mongodb" data-toggle="tab">Mongodb</a></li>
        <li><a href="#files" data-toggle="tab">Files</a></li>
    </ul>
    <div class="debugger"><a :href="basic.request_url" :title="basic.request_url" target="_self">ReqSrc</a></div>
    <div class="tab-content">
        <div class="tab-pane" id="basic">
            <h4>Basic Information</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td style="width: 5%">#</td>
                    <td>name</td>
                    <td>value</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(value, name, index) in basic">
                    <td>{{index}}</td>
                    <td>{{name}}</td>
                    <td><span :class="{warning:name.startsWith('opcache.') && value==='1'}">{{value}}</span></td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="dependencies">
            <h4>Dependencies({{Object.keys(dependency_values.filter(d=>is_show_dependency(d))).length}}) <label><input type="checkbox"
                                                                                 v-model="dependency_non_singleton_only"><small>Non
                Singleton Only</small>
                </input></label> <label><input type="checkbox"
                                              v-model="dependency_ignore_controller"><small> Ignore Controllers</small>
                </input></label></h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td width="5%">#</td>
                    <td width="5%">object_id</td>
                    <td width="40%">id</td>
                    <td>properties</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(item, id, index) in dependencies"
                    :class="{danger:item.instance_count>1 && typeof(item.properties)!=='string',info:typeof(item.properties)==='string'}"
                    v-if="is_show_dependency(item)">
                    <td>{{index}}</td>
                    <td :title="'instance_count: '+ item.instance_count">#{{item.object_id}}</td>
                    <td :title="item.class">
                        <pre>{{id}}
                            <div v-if="!id.startsWith(item.class)">=> {{item.class}}</div>
                        </pre>
                    </td>
                    <td :title="json_stringify(item.properties)">
                        <pre>{{item.properties|json 4}}</pre>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="contexts">
            <h4>Contexts({{Object.keys(dependency_values.filter(d => d.properties.context)).length}})</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td width="5%">#</td>
                    <td width="5%">object_id</td>
                    <td width="40%">id</td>
                    <td>contextors</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(item, id, index) in dependencies"
                    v-if="item.properties.context">
                    <td>{{index}}</td>
                    <td>#{{item.object_id}}</td>
                    <td :title="item.class">
                        <pre>{{id}}
                            <div v-if="!id.startsWith(item.class)">=> {{item.class}}</div>
                        </pre>
                    </td>
                    <td :title="json_stringify(item.properties.context)">
                        <pre>{{item.properties.context|json 4}}</pre>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="view">
            <h4>Renderer Files({{view.length}})</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td style="width: 5%">#</td>
                    <td style="width: 20%">file</td>
                    <td>vars</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(item, index) in view">
                    <td>{{index}}</td>
                    <td :title="item.file">{{item.base_name}}</td>
                    <td>
                        <pre :title="json_stringify(item.vars)">{{item.vars|json 4}}</pre>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="config">
            <h4>Config({{Object.keys(dependencies['ManaPHP\\Di\\ConfigInterface'].properties.config).length}})</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td style="width: 5%">#</td>
                    <td>name</td>
                    <td>value</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(value,name, index) in dependencies['ManaPHP\\Di\\ConfigInterface'].properties.config">
                    <td>{{index}}</td>
                    <td>{{name}}</td>
                    <td :title="json_stringify(value)">
                        <pre>{{value|json 4}}</pre>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="global">
            <h4><span class="text-uppercase">{{global_type}}</span> Data</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td style="width: 5%">#</td>
                    <td style="width: 15%">name</td>
                    <td>value</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(value, name, index) in dependencies['ManaPHP\\Http\\RequestInterface'].properties.context[global_type]">
                    <td>{{ index }}</td>
                    <td>{{ name }}</td>
                    <td>{{ value }}</td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="log">
            <h4>Log Messages({{logger.log.length}})
                <small><select v-model="logger.level" title="">
                    <option v-for="(intLevel,strLevel) in logger.levels" :value="intLevel">{{strLevel}}</option>
                </select></small>
            </h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td>#</td>
                    <td>time</td>
                    <td>level</td>
                    <td>category</td>
                    <td>location</td>
                    <td>message</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(log, index) in logger.log" v-if="logger.levels[log.level] <= logger.level">
                    <td>{{index + 1}}</td>
                    <td>{{log.time}}</td>
                    <td>{{log.level}}</td>
                    <td>{{log.category}}</td>
                    <td>{{log.file}}:{{log.line}}</td>
                    <td :title="json_pretty(log.message)" :class="logLevelClass(log.level)">{{log.message}}</td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="events">
            <h4>Events({{events.length}})</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td>#</td>
                    <td>event</td>
                    <td>source</td>
                    <td>data</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(event, index) in events">
                    <td>{{index}}</td>
                    <td>{{event.event}}</td>
                    <td>{{event.source}}</td>
                    <td>{{event.data}}</td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="sql">
            <h4>SQL({{sql.count}})
                <small><label><input type="checkbox" checked v-model="sql_executed"> Executed</label></small>
            </h4>
            <div v-if="sql_executed">
                <table class="table table-bordered table-condensed">
                    <thead>
                    <tr>
                        <td style="width: 50px">#</td>
                        <td>executed sql</td>
                        <td style="width: 50px">rows</td>
                        <td>elapsed</td>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="(item, index) in sql.executed" :title="json_stringify(item)">
                        <td>{{index}}</td>
                        <td>{{item.emulated.replace(/\[([\w]+)\]/g, '`$1`')}}</td>
                        <td>{{item.row_count}}</td>
                        <td>{{item.elapsed}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
            <div v-else>
                <table class="table table-bordered table-condensed">
                    <thead>
                    <tr>
                        <td style="width: 50px">#</td>
                        <td>prepared sql</td>
                        <td style="width: 50px">count</td>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="(count, sql, index) in sql.prepared">
                        <td>{{index}}</td>
                        <td>{{sql.replace(/\[([\w]+)\]/g, '`$1`')}}</td>
                        <td>{{count}}</td>
                    </tr>
                    </tbody>
                </table>
            </div>
        </div>
        <div class="tab-pane" id="mongodb">
            <h4>Mongodb({{mongodb.length}})</h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td>#</td>
                    <td>type</td>
                    <td>raw</td>
                    <td>shell</td>
                    <td>elapsed</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(item, index) in mongodb">
                    <td>{{index}}</td>
                    <td>{{item.type}}</td>
                    <td>{{item.raw|json 4}}</td>
                    <td>{{item.shell}}</td>
                    <td>{{item.elapsed}}</td>
                </tr>
                </tbody>
            </table>
        </div>
        <div class="tab-pane" id="files">
            <h4>IncludedFiles({{included_files_computed.length}}) <label><input type="checkbox"
                                                                                v-model="included_files_application_only">
                <small>Ignore Framework Files</small>
                </input></label></h4>
            <table class="table table-bordered table-condensed">
                <thead>
                <tr>
                    <td style="width: 5%">#</td>
                    <td>file</td>
                </tr>
                </thead>
                <tbody>
                <tr v-for="(file, index) in included_files_computed">
                    <td>{{index}}</td>
                    <td>{{file}}</td>
                </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/jquery@1.11.3/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/js/bootstrap.min.js"></script>
<script src='https://cdn.jsdelivr.net/npm/vue@2.6.9/dist/vue.min.js'></script>

<script>
    $(function () {
        $('#tabs a').on('shown.bs.tab', function (e) {
            localStorage.setItem('__debugger.last', e.target.hash);
        })

        let hash = localStorage.getItem('__debugger.last') || '#basic';
        $("a[href='" + hash + "']").tab('show');
    });

    let data = DEBUGGER_DATA;

    data.dependency_values = Object.values(data.dependencies);
    for (let id in data.dependencies) {
        let dependency = data.dependencies[id];
        dependency.instance_count = (new Set(data.dependency_values.filter(d => d.class == dependency.class).map(d => (d.object_id)))).size
    }

    data['included_files_application_only'] = true;
    data['sql_executed'] = true;
    data['global_type'] = 'request';
    data['dependency_non_singleton_only'] = false;
    data['dependency_ignore_controller'] = false;

    var app = new Vue({
        el: '#app',
        data: data,
        computed: {
            included_files_computed: function () {
                if (data['included_files_application_only']) {
                    var computed = [];
                    for (var file of data['included_files']) {
                        if (file.indexOf('/vendor/') < 0 && file.indexOf('framework') < 0) {
                            computed.push(file);
                        }
                    }
                    return computed;
                } else {
                    return data['included_files'];
                }
            }
        },
        methods: {
            logLevelClass: function (level) {
                let map = {
                    emergency: 'bg-danger',
                    alert: 'bg-danger',
                    critical: 'bg-danger',
                    error: 'bg-danger',
                    warning: 'bg-warning',
                    notice: 'bg-warning',
                    info: 'bg-info',
                    debug: '',
                };

                return map[level];
            },
            json_stringify: function (data) {
                return JSON.stringify(data, null, 4);
            },
            json_pretty: function (str) {
                if (str === '') {
                    return '';
                } else if (str[0] === '{' || str[0] === ']') {
                    return JSON.stringify(JSON.parse(str), null, 4);
                } else {
                    return str;
                }
            },
            is_show_dependency: function (item) {
                return (!this.dependency_non_singleton_only || (item.instance_count > 1 && typeof (item.properties) !== 'string'))
                        && (!this.dependency_ignore_controller || !item.class.includes('Controllers'))
            },
        }
    })
</script>
</body>
</html>